#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>

struct __myfile
{
    int fd;
    char buff[1024];
    int end;   //当前缓冲区的结尾
};
typedef struct __myfile MyFIle;

MyFIle* _fopen(const char* pathname, const char* mode)
{
    assert(pathname);
    assert(mode);

    MyFIle* fp = NULL;
    if (strcmp(mode, "r") == 0)
    {

    }
    else if (strcmp(mode, "w") == 0)
    {

        int fd  = open(pathname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
        if (fd >= 0)
        {
             fp = (MyFIle*)malloc(sizeof(MyFIle));
             memset(fp, 0, sizeof(MyFIle));
             fp->fd = fd;
             fp->end = 0;
        }

    }
    else 
    {
        //什么都不做
    }

    return fp;
}

void _fputs(const char* str, MyFIle* fp)
{
    assert(str);
    assert(fp);

    //将内容写到缓冲区
    strcpy(fp->buff + fp->end, str);
    fp->end = fp->end + strlen(str);

    //暂时没有刷新,打印测试
    printf("%s\n", fp->buff);
    
    //暂且没有刷新,刷新策略是谁执行?通过c标准库逻辑,来刷新
    //效率提高体现?c提供了缓冲区,减少了IO的次数(不是数据量)
    //显示器行刷新
    if (fp->fd == 0)
    {

    }
    else if (fp->fd == 1)
    {
        //标准输出
        if (fp->buff[fp->end - 1] == '\n')
        {
           fprintf(stderr, "fflush: %s ", fp->buff); //stderr
            write(fp->fd, fp->buff, fp->end);
            fp->end = 0;
        }
    }
    else if (fp->fd == 2)
    {
        //标准错误
    }

}

void _fflush(MyFIle* fp)
{
    assert(fp);

    //有数据再刷新
    if (fp->end != 0)
    {
        //暂且认为刷新了,其实是吧数据放到了内核缓冲区
        write(fp->fd, fp->buff, fp->end);
        //真正将数据刷到磁盘
        syncfs(fp->fd);
        fp->end = 0;
    }
}

void _fclose(MyFIle* fp)
{
    assert(fp);

    _fflush(fp);
    close(fp->fd);
    free(fp);
}

int main()
{
   // close(1);
    MyFIle* fp = _fopen("log.txt", "w");
    if (fp == NULL)
    {
        perror("_fopen");
        return 1;
    }

    _fputs("one:hello fputs\n", fp);
   // sleep(1);
   // _fputs("two:hello fputs\n", fp);
   // sleep(1);
   // _fputs("three:hello fputs ", fp);
   // sleep(1);
   // _fputs("four:hello fputs\n", fp);
   // sleep(1);
   
    fork();
    _fclose(fp);
     return 0;
}
